package top.ywlog.permission.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import top.ywlog.permission.common.response.Result;
import top.ywlog.permission.common.response.ResultCode;
import top.ywlog.permission.exception.InterceptorException;
import top.ywlog.permission.exception.ParamException;
import top.ywlog.permission.exception.PermissionException;

import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;

/**
 * @author: Durian
 * @date: 2020/10/17 20:33
 * @description: 全局异常处理
 */
@Slf4j
@RestControllerAdvice
public class GlobExceptionController
{

    @ExceptionHandler({Exception.class})
    public Result error(Exception e)
    {
        log.error("系统错误: {}", e.getMessage());
        return Result.fail(ResultCode.SYSTEM_ERROR);
    }

    @ExceptionHandler({ParamException.class})
    public Result error(ParamException e)
    {
        log.error("参数错误: {}", e.getMessage());
        return Result.fail(ResultCode.PARAM_ERROR.getCode(), e.getLocalizedMessage());
    }

    @ExceptionHandler({InterceptorException.class})
    public Result interceptError(InterceptorException e)
    {
        log.error("拦截器异常: {}", e.getMessage());
        return Result.fail(ResultCode.SYSTEM_ERROR);
    }

    @ExceptionHandler(PermissionException.class)
    public Result noAuth(PermissionException e)
    {
        log.error("权限不足: {}", e.getMessage());
        return Result.fail(ResultCode.AUTH_ERROR);
    }

    @ExceptionHandler({BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    public Result paramError(Exception e)
    {
        log.error("参数错误: {}", errorResult(e));
        return Result.fail(ResultCode.PARAM_ERROR.getCode(), errorResult(e));
    }

    /**
     * 获取校验结果
     */
    private String errorResult(Exception e)
    {
        String msg = null;
        // BindException
        if (e instanceof BindException)
        {
            // getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)
            FieldError fieldError = ((BindException) e).getFieldError();
            if (fieldError != null)
            {
                msg = fieldError.getDefaultMessage();
            }
            // MethodArgumentNotValidException
        } else if (e instanceof MethodArgumentNotValidException)
        {
            BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
            // getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null)
            {
                msg = fieldError.getDefaultMessage();
            }
            // ValidationException 的子类异常ConstraintViolationException
        } else if (e instanceof ConstraintViolationException)
        {
            /*
             * ConstraintViolationException的e.getMessage()形如
             *     {方法名}.{参数名}: {message}
             *  这里只需要取后面的message即可
             */
            msg = e.getMessage();
            if (msg != null)
            {
                int lastIndex = msg.lastIndexOf(':');
                if (lastIndex >= 0)
                {
                    msg = msg.substring(lastIndex + 1).trim();
                }
            }
            // ValidationException 的其它子类异常
        } else
        {
            msg = "参数处理异常";
        }
        return msg;
    }
}
